package com.tigear.onenethttpsvc.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.tigear.onenethttpsvc.utils.OnenetHttpPushUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.io.UnsupportedEncodingException;
import java.util.Map;

/**
 * 此例程为OneNET HTTP推送接收处理例程
 * 为明文模式
 *
 */

@Slf4j
@RestController
@RequestMapping("onenet")
public class HttpPushController {


    /**
     * 功能说明： URL&Token验证接口。如果验证成功返回msg的值，否则返回其他值。
     *
     * @param msg       验证消息
     * @param nonce     随机串
     * @param signature 签名
     * @return msg值
     */
    @GetMapping("/receive")
    public String checkToken(@RequestParam(value = "msg") String msg,
                             @RequestParam(value = "nonce") String nonce,
                             @RequestParam(value = "signature") String signature) throws UnsupportedEncodingException {

        log.info("url&token check: msg:{} nonce{} signature:{}", msg, nonce, signature);

        //如果用户不想验证token，可以选择跳过CheckToken计算过程，直接返回msg参数值
        log.info("no token validation");
        return msg;

        //该Token在OneNet HTTP 推送配置中设置， 请改成您自己设置的
//        final String token = "12345678";
//        if (OnenetHttpPushUtil.checkToken(msg, nonce, signature, token)) {
//            return msg;
//        } else {
//            return "error";
//        }
    }

    /**
     * 功能描述：第三方平台数据接收。<p>
     * <ul>注:
     * <li>1.OneNet平台为了保证数据不丢失，有重发机制，如果重复数据对业务有影响，数据接收端需要对重复数据进行排除重复处理。</li>
     * <li>2.OneNet每一次post数据请求后，等待客户端的响应都设有时限，在规定时限内没有收到响应会认为发送失败。
     * 接收程序接收到数据时，尽量先缓存起来，再做业务逻辑处理。</li>
     * </ul>
     *
     * @param body 数据消息
     * @return 任意字符串。OneNet平台接收到http 200的响应，才会认为数据推送成功，否则会重发。
     */
     @PostMapping("/receive")
     public String receive(@RequestBody String body) {
         log.info("data receive:  body String --- " + body);

         //对数据进行处理
         JSONObject jsonObject = JSON.parseObject(body);
         JSONObject msgObject = jsonObject.getJSONObject("msg");

         //获取消息类型和设备名称
         String deviceName = msgObject.getString("deviceName");
         String messageType = msgObject.getString("messageType");

         log.info("message " + messageType + " device " + deviceName);

         if(messageType != null) {
             switch (messageType) {
                 case "notify": //物模型属性事件推送
                     this.notifyMessageHandler(msgObject);
                     break;
                 case "reply"://设备服务调用
                     this.replyMessageHandler(msgObject);
                     break;
                 case "lbsAndWifi":// 设备位置信息
                     this.lbsMessageHandler(msgObject);
                     break;
                 case "lifeCycle":
                     this.lifeCycleMessageHandler(msgObject);
                     break;
                 default:
                     log.info("unknown message type");
                     break;
             }
         }

         return "ok";
     }

    /**
     * 生命周期事件推送s
     * @param msgObject
     */
    private void lifeCycleMessageHandler(JSONObject msgObject) {

    }

    /**
     * 物模型属性事件推送
     * @param msgObject
     */
    void notifyMessageHandler(JSONObject msgObject ){
        /*
         notifytype: 物模型类型property：物模型属性event：物模型事件
         */
        String notifyType = msgObject.getString("notifyType");
        log.info("notifyType " + notifyType);

        JSONObject paramsObject = msgObject.getJSONObject("data").getJSONObject("params");

        for (Map.Entry<String, Object> entry : paramsObject.entrySet()){
            log.info(entry.getKey() +  " : " + entry.getValue());
        }
     }

    /**
     * 设备服务调用
     * @param msgObject
     */
    void replyMessageHandler(JSONObject msgObject) {

        //服务调用输入参数
        JSONObject paramsObject = msgObject.getJSONObject("request").getJSONObject("params");
        log.info("request ");

        for (Map.Entry<String, Object> entry : paramsObject.entrySet()){
            log.info(entry.getKey() +  " : " + entry.getValue());
        }

        //服务调用返回数据
         log.info("response ");
        JSONObject responseObject = msgObject.getJSONObject("response");

        int code = responseObject.getInteger("code");
        log.info("code " + code);

        JSONObject dataObject = responseObject.getJSONObject("data");
        for (Map.Entry<String, Object> entry : dataObject.entrySet()){
            log.info(entry.getKey() +  " : " + entry.getValue());
        }

    }

    /**
     * 设备位置信息
     */
    void lbsMessageHandler(JSONObject msgObject) {
        JSONObject dataObject = msgObject.getJSONObject("data");

        log.info("location ");
        log.info(dataObject.getDouble("lon").toString());
        log.info(dataObject.getDouble("lat").toString());

    }
}
